package org.zjvis.datascience.service;

import java.util.*;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
//import javafx.concurrent.Task;
//import netscape.javascript.JSObject;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.zjvis.datascience.common.algo.BaseAlg;
import org.zjvis.datascience.common.dto.*;
import org.zjvis.datascience.common.enums.*;
import org.zjvis.datascience.common.etl.BaseETL;
import org.zjvis.datascience.common.model.TaskItems;
import org.zjvis.datascience.common.model.TaskMeta;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.util.ToolUtil;
import org.zjvis.datascience.common.vo.MLModelVO;
import org.zjvis.datascience.common.vo.TaskVO;
import org.zjvis.datascience.common.vo.project.ProjectIdVO;
import org.zjvis.datascience.common.vo.project.ProjectNameVO;
import scala.beans.BeanDisplayName;

/**
 * @description Panel 右侧算子面板加载 Service
 * @date 2021-12-28
 */
@Service
public class PanelService {

    @Autowired
    private OperatorTemplateService operatorTemplateService;

    @Autowired
    private MLModelService mlModelService;

    @Autowired
    private FolderService folderService;

    private static List<String> algNames = new ArrayList<>();

    private static List<String> etls = new ArrayList<>();

    private static List<String> featureEngAlgo = new ArrayList<>();

    private static Map<String, String> urlHelpers = new HashMap<>();

    private static Map<String, String> enumToUrlKeyMap = new HashMap<>();

    static {
        etls.add("Filter");
        etls.add("Join");
        etls.add("Sample");
        etls.add("Sql");
        etls.add("Union");
        etls.add("imputation_stat");
        etls.add("imputation_multi");
        etls.add("PivotTable");
    }

    static {
        featureEngAlgo.add("standardization");
        featureEngAlgo.add("timeseries_decompose");
        featureEngAlgo.add("smoothing");
        featureEngAlgo.add("timeseries_shift");
    }

    static {
        algNames.add("DBscanAlg");
        algNames.add("KmeansAlg");
        algNames.add("PcaDenseAlg");
        algNames.add("TsneAlg");
        algNames.add("LLEAlg");
//        algNames.add("StatisticsAnomalyAlg");
//        algNames.add("LinearRegressionAlg");
//        algNames.add("LogisticRegressionAlg");
        algNames.add("FPGrowthAlg");
        algNames.add("PrefixSpanAlg");
        //algNames.add("SelfDefineAlg");
        algNames.add("anomaly_stat");
        algNames.add("anomaly_knn");
        algNames.add("IsolateForestAlg");
//        algNames.add("simulate");
//        algNames.add("simulate_new");
//        algNames.add("simulate_inverse");
    }

    static {
        /*
         *算子库
         */
        //聚类DBSCAN
        urlHelpers.put("DBscanAlg", "https://nebula-inner.lab.zjvis.net/docs/#/formula_guide?id=dbscan");
        //聚类K-means
        urlHelpers.put("KmeansAlg", "https://nebula-inner.lab.zjvis.net/docs/#/formula_guide?id=k-means");
        //降维-PCA
        urlHelpers.put("PcaDenseAlg", "https://nebula-inner.lab.zjvis.net/docs/#/formula_guide?id=pca");
        //降维-TSNE
        urlHelpers.put("TsneAlg", "https://nebula-inner.lab.zjvis.net/docs/#/formula_guide?id=tsne");
        //降维-LLE
        urlHelpers.put("LLEAlg", "https://nebula-inner.lab.zjvis.net/docs/#/formula_guide?id=lle");
//        //异常检测 stat
//        urlHelpers.put("StatisticsAnomalyAlg", "https://en.wikipedia.org/wiki/Statistical_hypothesis_testing");
        //异常检测 iso
        urlHelpers.put("IsolateForestAlg", "https://nebula-inner.lab.zjvis.net/docs/#/formula_guide?id=iso_forest-%e9%9a%8f%e6%9c%ba%e6%a3%ae%e6%9e%97");
        //频繁模式挖掘 FPGrowthAlg"
        urlHelpers.put("FPGrowthAlg", "https://nebula-inner.lab.zjvis.net/docs/#/formula_guide?id=fp-growth");
        //频繁模式挖掘 Prefix
        urlHelpers.put("PrefixSpanAlg", "https://nebula-inner.lab.zjvis.net/docs/#/formula_guide?id=prefixspan");
//        //自定义算子
//        urlHelpers.put("SelfDefineAlg", "https://nebula-inner.lab.zjvis.net/docs/#/model?id=%e8%87%aa%e5%ae%9a%e4%b9%89%e7%ae%97%e5%ad%90");

        urlHelpers.put("LinearRegressionAlg", "https://cf.zjvis.org/pages/viewpage.action?pageId=19202191#id-%E7%AE%97%E5%AD%90%E4%BD%BF%E7%94%A8%E6%8C%87%E5%BC%95-%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92");

        urlHelpers.put("LogisticRegressionAlg", "https://cf.zjvis.org/pages/viewpage.action?pageId=19202191#id-%E7%AE%97%E5%AD%90%E4%BD%BF%E7%94%A8%E6%8C%87%E5%BC%95-%E9%80%BB%E8%BE%91%E5%9B%9E%E5%BD%92");

        /*
         *算子库
         */
        //ETL/清洗 Filter
        urlHelpers.put("Filter", "https://nebula-inner.lab.zjvis.net/docs/#/data_clean?id=%e2%91%a0-filter");
        //ETL/清洗 Join
        urlHelpers.put("Join", "https://nebula-inner.lab.zjvis.net/docs/#/data_clean?id=%e2%91%a0-join");
        //ETL/清洗 Sample
        urlHelpers.put("Sample", "https://nebula-inner.lab.zjvis.net/docs/#/data_clean?id=%e2%91%a1-sample");
        //ETL/清洗 SQL
        urlHelpers.put("Sql", "https://nebula-inner.lab.zjvis.net/docs/#/data_clean?id=_3%e3%80%81sql%e6%94%af%e6%8c%81");
        //ETL/清洗 Union
        urlHelpers.put("Union", "https://nebula-inner.lab.zjvis.net/docs/#/data_clean?id=%e2%91%a1-union");
        //ETL/清洗 清洗
        urlHelpers.put("Clean", "https://nebula-inner.lab.zjvis.net/docs/#/data_clean?id=%e6%95%b0%e6%8d%ae%e6%b8%85%e6%b4%97");
        //图构建
        urlHelpers.put("Graph", "https://nebula-inner.lab.zjvis.net/docs/#/graph_network");

        /*
        经济7步算子
         */
        urlHelpers.put("imputation_stat", "https://nebula-dev.zjvis.net/docs/#/data_clean?id=_4%e3%80%81-%e7%bc%ba%e5%a4%b1%e5%80%bc%e6%8f%92%e8%a1%a5");
        urlHelpers.put("imputation_multi", "https://nebula-dev.zjvis.net/docs/#/data_clean?id=_4%e3%80%81-%e7%bc%ba%e5%a4%b1%e5%80%bc%e6%8f%92%e8%a1%a5");
        urlHelpers.put("anomaly_stat", "https://nebula-dev.zjvis.net/docs/#/formula_guide?id=%e5%bc%82%e5%b8%b8%e5%80%bc%e6%a3%80%e6%b5%8b-%e7%bb%9f%e8%ae%a1");
        urlHelpers.put("anomaly_knn", "https://nebula-dev.zjvis.net/docs/#/formula_guide?id=%e5%bc%82%e5%b8%b8%e5%80%bc%e6%a3%80%e6%b5%8b-%e8%bf%91%e9%82%bb");
        urlHelpers.put("standardization", "https://nebula-dev.zjvis.net/docs/#/data_clean?id=_1%e3%80%81%e6%a0%87%e5%87%86%e5%8c%96");
        urlHelpers.put("timeseries_decompose", "https://nebula-dev.zjvis.net/docs/#/data_clean?id=_2%e3%80%81%e6%97%b6%e9%97%b4%e5%ba%8f%e5%88%97%e5%88%86%e8%a7%a3");
        urlHelpers.put("smoothing", "https://nebula-dev.zjvis.net/docs/#/data_clean?id=_3%e3%80%81%e6%95%b0%e6%8d%ae%e5%b9%b3%e6%bb%91");
    }

    static {
        enumToUrlKeyMap.put("DBSCAN", "DBscanAlg");
        enumToUrlKeyMap.put("KMEANS", "KmeansAlg");
        enumToUrlKeyMap.put("PCA_DENSE", "PcaDenseAlg");
        enumToUrlKeyMap.put("TSNE", "TsneAlg");
        enumToUrlKeyMap.put("LLE", "LLEAlg");
//        enumToUrlKeyMap.put("STAT_ANOMALY", "StatisticsAnomalyAlg");
        enumToUrlKeyMap.put("ISO_FOREST", "IsolateForestAlg");
        enumToUrlKeyMap.put("LINEARREGRE", "LinearRegressionAlg");
        enumToUrlKeyMap.put("LOGREGRE", "LogisticRegressionAlg");
        enumToUrlKeyMap.put("FP_GROWTH", "FPGrowthAlg");
        enumToUrlKeyMap.put("PREFIX_SPAN", "PrefixSpanAlg");
        enumToUrlKeyMap.put("FILTER", "Filter");
        enumToUrlKeyMap.put("JOIN", "Join");
        enumToUrlKeyMap.put("SAMPLE", "Sample");
        enumToUrlKeyMap.put("UNION", "Union");
        enumToUrlKeyMap.put("SQL", "Sql");
        //enumToUrlKeyMap.put("SELF_DEFINE", "SelfDefineAlg");
    }

    private boolean isContainKey(String name, String searchKey) {
        String lowerName = name.toLowerCase();
        String lowerKey = searchKey.toLowerCase();
        return lowerName.contains(lowerKey);
    }

    private TaskMeta loadJLAB(PanelDTO panelDTO, String searchKey, List<TaskMeta> taskMetas) {

        TaskMeta taskMeta = new TaskMeta("自定义算子(new)",TaskTypeEnum.TASK_TYPE_JLAB.getVal()
                , SubTypeEnum.SELF_DEFINE.getVal(), 1,false,1L,false,null);

        if (StringUtils.isEmpty(searchKey) || isContainKey("自定义算子(new)", searchKey)) {
            if (StringUtils.isNotEmpty(searchKey)) {
                taskMeta.setHighLight(true);
            }

            taskMetas.add(taskMeta);
            panelDTO.add(taskMeta);
        }
        return taskMeta;
    }

        public JSONArray getTemplateParamList(String fileName) {
        String json = new ToolUtil().readJsonFile(fileName);
        if (json.length() == 0) {
            return null;
        }
        return JSONArray.parseArray(json);
    }

    private PanelDTO loadFeatureEngAlgo(PanelDTO panelDTO, String searchKey) {
        TaskItems featureTaskItems = new TaskItems();
        featureTaskItems.setName(SubTypeEnum.FEATURE_ENGINEERING.getDesc());
        List<TaskMeta> featureTaskMetas = new ArrayList<>();
        for (String featureTask : featureEngAlgo) {

//            String TPL_FILENAME = String.format("template/algoPy/%s.json", featureTask);
//            JSONArray setParams = getTemplateParamList(TPL_FILENAME);
            String displayName = AlgPyEnum.getEnumByName(featureTask).getDesc();
            if (StringUtils.isEmpty(searchKey) || isContainKey(displayName, searchKey)) {
                TaskMeta taskMeta = new TaskMeta(displayName, TaskTypeEnum.TASK_TYPE_ALGOPY.getVal(),
                        SubTypeEnum.FEATURE_ENGINEERING.getVal(), AlgPyEnum.getEnumByDesc(displayName).getVal(), false, 0L
                        , false, urlHelpers.get(featureTask));
                if (StringUtils.isNotEmpty(searchKey) && isContainKey(displayName, searchKey)) {
                    taskMeta.setHighLight(true);
                }
                featureTaskMetas.add(taskMeta);
                panelDTO.add(taskMeta);
            }


        }
        featureTaskItems.setItems(featureTaskMetas);
        featureTaskItems.setSubType(SubTypeEnum.FEATURE_ENGINEERING.getVal());
        panelDTO.add(featureTaskItems);
        return panelDTO;
    }

    private Set<String> getFavouriteOperator(PanelDTO panelDTO) {
        List<TaskMeta> taskMetas = panelDTO.getSearchList();
        Set<String> sets = new HashSet<>();
        for (TaskMeta taskMeta : taskMetas) {
            sets.add(taskMeta.getName());
        }
        return sets;
    }

//    private void loadFavouriteOperator(PanelDTO panelDTO, String searchKey) {
//        TaskItems taskItems = new TaskItems();
//        taskItems.setName(SubTypeEnum.FAVOURITE.getDesc());
//        taskItems.setSubType(SubTypeEnum.FAVOURITE.getVal());
//        List<TaskMeta> taskMetas = new ArrayList<>();
//        List<OperatorFavouriteDTO> favouriteDTOS = operatorFavouriteService.query();
//        for (OperatorFavouriteDTO dto: favouriteDTOS) {
//            boolean isEdited = false;
//            String descUrl = TaskTypeEnum.TASK_TYPE_DEFINE.getVal() == dto.getTaskType()
//                ? OperatorTemplateService.SELF_DEFINE_SDK
//                : urlHelpers.get(enumToUrlKeyMap.get(dto.getAlgName()));
//            TaskMeta taskMeta = new TaskMeta(dto.getAlgName(), dto.getTaskType(),
//                SubTypeEnum.FAVOURITE.getVal(), dto.getAlgType(), dto.isStarred(), dto.getId(),
//                dto.isEdited(), descUrl);
//            taskMeta.setStatus(dto.getStatus());
//            taskMeta.setSuggestion(dto.getSuggestion());
//            if (StringUtils.isEmpty(searchKey) || isContainKey(dto.getAlgName(), searchKey)) {
//                taskMetas.add(taskMeta);
//                panelDTO.add(taskMeta);
//            }
//        }
//        taskItems.setItems(taskMetas);
//        panelDTO.add(taskItems);
//    }

    //    private void loadDataCleanOperator(PanelDTO panelDTO, String searchKey, Set<String> favouriteOperators) {
//        String name = "清洗";
//        if (StringUtils.isNotEmpty(searchKey) && isContainKey(name, searchKey) && favouriteOperators.contains(name)) {
//            // 搜索的时候收藏中如果存在算子，则只是展示搜藏结果
//            return;
//        }
//        TaskItems taskItems = new TaskItems();
//        taskItems.setName(SubTypeEnum.DATA_CLEANING.getDesc());
//        taskItems.setSubType(SubTypeEnum.DATA_CLEANING.getVal());
//        List<TaskMeta> taskMetas = new ArrayList<>();
//        TaskMeta taskMeta = new TaskMeta("清洗", TaskTypeEnum.TASK_TYPE_CLEAN.getVal(), SubTypeEnum.DATA_CLEANING.getVal(), 1,
//                favouriteOperators.contains("清洗"), 0L, true, "");
//        taskMetas.add(taskMeta);
//        taskItems.setItems(taskMetas);
//        panelDTO.add(taskItems);
//    }
    private void loadCleanseETLOperator(PanelDTO panelDTO, String searchKey) {

    }

    private void loadGraphNetOperator(PanelDTO panelDTO, String searchKey, Set<String> favouriteOperators) {
        String name = "图网络构建";
        if (StringUtils.isNotEmpty(searchKey) && isContainKey(name, searchKey) && favouriteOperators.contains(name)) {
            // 搜索的时候收藏中如果存在算子，则只是展示搜藏结果
            return;
        }
        TaskItems taskItems = new TaskItems();
        taskItems.setName(SubTypeEnum.GRAPH_NET.getDesc());
        taskItems.setSubType(SubTypeEnum.GRAPH_NET.getVal());
        List<TaskMeta> taskMetas = new ArrayList<>();
        TaskMeta taskMeta = new TaskMeta(name, TaskTypeEnum.TASK_TYPE_GRAPH.getVal(), SubTypeEnum.GRAPH_NET.getVal(), AlgEnum.GRAPH_BUILD.getVal(),
                favouriteOperators.contains(name), 0L, true, urlHelpers.get("Graph"));
        taskMetas.add(taskMeta);
        taskItems.setItems(taskMetas);
        panelDTO.add(taskItems);
    }

    public PanelDTO loadPanel(ProjectNameVO vo) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        String searchKey = vo.getSearchName();
        PanelDTO panelDTO = new PanelDTO();
        PanelDTO panelSearchDTO = new PanelDTO();

        Set<String> favouriteOperators = this.getFavouriteOperator(panelDTO);
        SubTypeEnum[] subTypes = SubTypeEnum.values();
        Map<String, List<TaskMeta>> maps = new HashMap<>();
        Map<String, Integer> subTypeMap = new HashMap<>();
        for (SubTypeEnum subType : subTypes) {
            String classify = subType.getDesc();
            if (!maps.containsKey(classify)) {
                maps.put(classify, new ArrayList<>());
                subTypeMap.put(classify, subType.getVal());
            }
        }
        //*******************************************清洗/ETL操作******************************************************
        TaskItems etlTaskItems = new TaskItems();
        etlTaskItems.setName(SubTypeEnum.ETL_OPERATE.getDesc());
        List<TaskMeta> etlTaskMeta = new ArrayList<>();
        for (String etl : etls) {
            TaskMeta taskMeta;
            String displayName;
            int subType;
            int algType;
            int taskType;
            String name;
            if (etl.equals(AlgPyEnum.IMPUTATION_STAT.getName()) || etl.equals(AlgPyEnum.IMPUTATION_MULTI.getName())) {
                AlgPyEnum alg = AlgPyEnum.getEnumByName(etl);
                taskType = TaskTypeEnum.TASK_TYPE_ALGOPY.getVal();
                subType = SubTypeEnum.ETL_OPERATE.getVal();
                algType = alg.getVal();
                displayName = alg.getDesc();
            } else {
                Class<?> c = Class.forName("org.zjvis.datascience.common.etl." + etl);
                Object obj = c.newInstance();
                BaseETL baseETL = (BaseETL) obj;
                displayName = baseETL.getName();
                taskType = TaskTypeEnum.TASK_TYPE_ETL.getVal();
                subType = baseETL.getSubType();
                algType = ETLEnum.valueOf(displayName).getVal();
            }
            if (StringUtils.isEmpty(searchKey) || isContainKey(displayName, searchKey)) {
                taskMeta = new TaskMeta(displayName, taskType,
                        subType, algType, false, 0L
                        , false, urlHelpers.get(etl));
                if (StringUtils.isNotEmpty(searchKey)) {
                    taskMeta.setHighLight(true);
                }
                etlTaskMeta.add(taskMeta);
                panelDTO.add(taskMeta);
            }
        }
        if (StringUtils.isEmpty(searchKey) || isContainKey("清洗", searchKey)
                || isContainKey("clean", searchKey)) {
            TaskMeta taskMetaCleanse = new TaskMeta("清洗", TaskTypeEnum.TASK_TYPE_CLEAN.getVal()
                    , SubTypeEnum.ETL_OPERATE.getVal(), 0,
                    favouriteOperators.contains("清洗"), 0L, true, urlHelpers.get("Clean"));
            if (StringUtils.isNotEmpty(searchKey)) {
                taskMetaCleanse.setHighLight(true);
            }
            etlTaskMeta.add(taskMetaCleanse);
            panelDTO.add(taskMetaCleanse);
        }
        etlTaskItems.setItems(etlTaskMeta);
        etlTaskItems.setSubType(SubTypeEnum.ETL_OPERATE.getVal());
        panelDTO.add(etlTaskItems);

        //***********************************************特征工程**************************************************

        panelDTO = loadFeatureEngAlgo(panelDTO,searchKey);

        //***********************************************算子库**************************************************

        TaskItems generalTaskItems = new TaskItems();
        generalTaskItems.setName(SubTypeEnum.GENERAL_ALGORITHM.getDesc());
        List<TaskMeta> generalTaskMetas = new ArrayList<>();
        for (String algName : algNames) {
            TaskMeta taskMeta;
            String displayName;
            String name;
            int subType;
            int algType;
            int taskType;
            if (algName.equals(AlgPyEnum.ANOMALY_STAT.getName()) || algName.equals(AlgPyEnum.ANOMALY_KNN.getName()) ||
                algName.equals(AlgPyEnum.SIMULATE.getName()) || algName.equals(AlgPyEnum.SIMULATE_NEW.getName())
                || algName.equals(AlgPyEnum.SIMULATE_INVERSE.getName())){
                AlgPyEnum alg = AlgPyEnum.getEnumByName(algName);
                displayName = alg.getDesc();
                taskType = TaskTypeEnum.TASK_TYPE_ALGOPY.getVal();
                subType = SubTypeEnum.GENERAL_ALGORITHM.getVal();
                algType = alg.getVal();
            } else {
                Class<?> c = Class.forName("org.zjvis.datascience.common.algo." + algName);
                Object obj = c.newInstance();
                BaseAlg alg = (BaseAlg) obj;
                String subTypeName = "算子库";
                name = alg.getName();
                displayName = AlgEnum.valueOf(name).getDesc();
                taskType = TaskTypeEnum.TASK_TYPE_ALGO.getVal();
                subType = alg.getSubType();
                algType = AlgEnum.valueOf(name).getVal();
            }
            if (StringUtils.isEmpty(searchKey) || isContainKey(displayName, searchKey)) {
                taskMeta = new TaskMeta(displayName,
                        taskType, subType, algType
                        , false, 0L, false, urlHelpers.get(algName));
                if (StringUtils.isNotEmpty(searchKey)) {
                    taskMeta.setHighLight(true);
                }
                generalTaskMetas.add(taskMeta);
                panelDTO.add(taskMeta);
            }
        }

        if (StringUtils.isEmpty(searchKey) || isContainKey("JLAB", searchKey)) {
            this.loadJLAB(panelDTO, searchKey, generalTaskMetas);
        }

        generalTaskItems.setItems(generalTaskMetas);
        generalTaskItems.setSubType(SubTypeEnum.GENERAL_ALGORITHM.getVal());

        panelDTO.add(generalTaskItems);


        this.loadGraphNetOperator(panelDTO, searchKey, favouriteOperators);
        //***********************************************我的模型**************************************************

        panelDTO = loadMLModel(panelDTO, vo);

        return panelDTO;
    }

    /**
     * 获取已经导出的在项目里的ML model
     * @param panelDTO
     * @param vo
     * @return
     */
    public PanelDTO loadMLModel(PanelDTO panelDTO, ProjectNameVO vo) {
        TaskItems modelTaskItems  = new TaskItems();
        modelTaskItems.setName(SubTypeEnum.MLMODEL.getDesc());

        MLModelVO modelInPanel = new MLModelVO();
        modelInPanel.setInPanel(1L);
        modelInPanel.setUserId(vo.getUserId());
        modelInPanel.setProjectId(vo.getProjectId());

        List<TaskMeta> modelTaskMetas = new ArrayList<>();

        List<MLModelDTO> modelDTOSinPanel = mlModelService.queryModelPanel(modelInPanel);
        for (MLModelDTO model : modelDTOSinPanel) {
            if (StringUtils.isEmpty(vo.getSearchName()) || isContainKey(model.getName(), vo.getSearchName())) {
                TaskMeta singleModelTaskMeta = new TaskMeta(model.getName(), TaskTypeEnum.TASK_TYPE_MODEL.getVal(), SubTypeEnum.MLMODEL.getVal(), 7,
                        false, new Long(model.getId()), true, "");
                if (StringUtils.isNotEmpty(vo.getSearchName()) && isContainKey(model.getName(), vo.getSearchName())) {
                    singleModelTaskMeta.setHighLight(true);
                }
                modelTaskMetas.add(singleModelTaskMeta);
                panelDTO.add(singleModelTaskMeta);
            }
        }
        MLModelVO modelvo = new MLModelVO();
        modelvo.setName(vo.getSearchName());
        modelvo.setProjectId(vo.getProjectId());
        modelvo.setUserId(vo.getUserId());
        List<FolderDTO> folderDTOS = mlModelService.getFolders(modelvo);
        for (FolderDTO folder : folderDTOS) {
            Long folderId = folder.getId();
            List<MLModelVO> modelsInFolder = mlModelService.queryModelByFolderId(folderId);
            //无搜索或搜索到文件夹后，加入所有文件夹内部模型
            if (StringUtils.isEmpty(vo.getSearchName()) || isContainKey(folder.getName(), vo.getSearchName())) {
                List<TaskMeta> modelInFolder = new ArrayList<>();
                Integer unfold = 0;
                if (modelsInFolder != null) {
                    for (MLModelVO model : modelsInFolder) {
                        String modelName = model.getName();
                        Long modelId = model.getId();
                        TaskMeta folderModelTaskMeta = new TaskMeta(modelName, TaskTypeEnum.TASK_TYPE_MODEL.getVal(), SubTypeEnum.MLMODEL.getVal(), 7,
                                false, modelId, true, "");
                        if (StringUtils.isNotEmpty(vo.getSearchName()) && isContainKey(modelName, vo.getSearchName())) {
                            unfold = 1;
                            folderModelTaskMeta.setHighLight(true);
                        }
                        if (StringUtils.isEmpty(vo.getSearchName())) {
                            panelDTO.add(folderModelTaskMeta);
                        }
                        modelInFolder.add(folderModelTaskMeta);
                    }
                }
                TaskMeta singleFolderTaskMeta = new TaskMeta(folder.getName(), TaskTypeEnum.TASK_TYPE_MODEL.getVal(), SubTypeEnum.MLMODEL.getVal(), 25,
                        true, new Long(folder.getId()), true, "", Math.toIntExact(folder.getUnfold()), modelInFolder);
                if (StringUtils.isNotEmpty(vo.getSearchName()) && isContainKey(folder.getName(), vo.getSearchName())) {
                    singleFolderTaskMeta.setHighLight(true);
                }
                singleFolderTaskMeta.setUnfold(unfold);
                modelTaskMetas.add(singleFolderTaskMeta);
                panelDTO.add(singleFolderTaskMeta);
            } else {//如果有搜索key且没有与文件夹名相匹配，则尝试匹配文件夹内部模型名称
                boolean hasModelMatched = false;
                List<TaskMeta> modelInFolder = new ArrayList<>();
                if (modelsInFolder != null) {
                    for (MLModelVO model : modelsInFolder) {
                        String modelName = model.getName();
                        Long modelId = model.getId();
                        if (isContainKey(modelName, vo.getSearchName())) {
                            TaskMeta folderModelTaskMeta = new TaskMeta(modelName, TaskTypeEnum.TASK_TYPE_MODEL.getVal(), SubTypeEnum.MLMODEL.getVal(), 7,
                                    false, modelId, true, "");
                            folderModelTaskMeta.setHighLight(true);
                            modelInFolder.add(folderModelTaskMeta);
                            panelDTO.add(folderModelTaskMeta);
                            hasModelMatched = true;
                        }
                    }
                }
                if (hasModelMatched) {
                    TaskMeta singleFolderTaskMeta = new TaskMeta(folder.getName(), TaskTypeEnum.TASK_TYPE_MODEL.getVal(), SubTypeEnum.MLMODEL.getVal(), 25,
                            true, new Long(folder.getId()), true, "", Math.toIntExact(folder.getUnfold()), modelInFolder);
                    singleFolderTaskMeta.setUnfold(1);
                    modelTaskMetas.add(singleFolderTaskMeta);
                    panelDTO.add(singleFolderTaskMeta);
                }
            }
        }
        modelTaskItems.setItems(modelTaskMetas);
        modelTaskItems.setSubType(SubTypeEnum.MLMODEL.getVal());
        panelDTO.add(modelTaskItems);
        return panelDTO;
    }

    /**
     * 复制某个panel （现阶段只针对 “我的模型”）下的所有内容，有文件夹的创建文件夹， 不是文件夹的，直接插入到新的项目中
     *
     * @param folder
     */
    public void batchCopy(TaskItems folder, Long newProjectId) {
        List<TaskMeta> items = folder.getItems();
        for (TaskMeta meta: items){
            if (meta.getIsFolder()){
                //复制folder 及 里面的内容
                FolderDTO newFolder = folderService.copyIntoNewProject(meta, newProjectId);
                if (meta.getModelInFolder().size() > 0){
                    //旧的folder中有模型
                    for(TaskMeta model: meta.getModelInFolder()){
                        MLModelDTO tmpModel = mlModelService.queryMetricsById(model.getId());
                        tmpModel.setId(null);
                        tmpModel.setProjectId(newProjectId);
                        tmpModel.setUserId(JwtUtil.getCurrentUserId());
                        tmpModel.setInvisible(ModelStatusEnum.COPIED.getVal());
                        tmpModel.setFolderId(newFolder.getId());
                        mlModelService.save(tmpModel);
                    }
                }
            }else {
                //仅仅是ML模型，插入到新的项目中
                //invisible -1 代表复制出来的ML model
                MLModelDTO tmpModel = mlModelService.queryMetricsById(meta.getId());
                tmpModel.setId(null);
                tmpModel.setProjectId(newProjectId);
                tmpModel.setUserId(JwtUtil.getCurrentUserId());
                tmpModel.setInvisible(ModelStatusEnum.COPIED.getVal());
                mlModelService.save(tmpModel);
            }
        }
    }
}
